﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEngine;

namespace Editor.Gmx.AutoGroup
{
    public class AutoGroupRule
    {
        public static bool ApplyImportRule(string assetPath, string movedFromAssetPath,
            AddressableAssetSettings settings, AutoGroupSetting autoSettings)
        {
            var dirty = false;
            //是否是需要操作的根目录
            var isOp = autoSettings.IsAssetInRoot(assetPath) && autoSettings.IsNeedAuto(assetPath);
            //如果发生asset移动 首先删除之前的entry
            if (!string.IsNullOrEmpty(movedFromAssetPath))
            {
                if (isOp)
                {
                    dirty = RemoveAssetEntry(settings, assetPath);
                }
            }

            if (isOp)
            {
                string lable = string.Empty;
                isOp = autoSettings.RuleExecute(assetPath, out lable);
                if (isOp)
                {
                    var entry = CreateOrUpdateAddressableAssetEntry(assetPath, settings, autoSettings, lable);
                    if (entry != null)
                        Debug.LogFormat("[AutoGroup] Entry created/updated for {0} with address {1} and labels {2}",
                            assetPath, entry.address, string.Join(", ", entry.labels));
                    dirty = true;
                }
                else
                {
                    if (RemoveAssetEntry(settings, assetPath))
                    {
                        dirty = true;
                    }
                }
            }
            else if (autoSettings.IsAssetInRoot(assetPath)) //在被管理的 art里 必须删除没有的
            {
                if (RemoveAssetEntry(settings, assetPath))
                {
                    dirty = true;
                }
            }

            return dirty;
        }


        private static bool RemoveAssetEntry(AddressableAssetSettings settings, string assetPath)
        {
            var guid = AssetDatabase.AssetPathToGUID(assetPath);
            var entry = settings.FindAssetEntry(guid);
            if (entry != null)
            {
                settings.RemoveAssetEntry(guid);
                Debug.LogFormat("[AutoGroup] : Entry removed for {0}", assetPath);
                return true;
            }

            return false;
        }

        public static AddressableAssetEntry CreateOrUpdateAddressableAssetEntry(string assetPath,
            AddressableAssetSettings settings, AutoGroupSetting autoSettings, string lable = "")
        {
            if (!TryGetGroup(settings, autoSettings._autoGroupName, out var autoGroup))
            {
                autoGroup = CreateAssetGroup<BundledAssetGroupSchema>(settings, autoSettings._autoGroupName);
                //添加Schema
                var templateSchema = autoSettings._groupTemplate.SchemaObjects;
                foreach (var schema in templateSchema.Where(schema => !autoGroup.HasSchema(schema.GetType())))
                    autoGroup.AddSchema(schema.GetType());
                autoSettings._groupTemplate.ApplyToAddressableAssetGroup(autoGroup);
            }

            var guid = AssetDatabase.AssetPathToGUID(assetPath);
            var entry = settings.FindAssetEntry(guid);
            if (entry == null || entry.parentGroup != autoGroup)
                entry = settings.CreateOrMoveEntry(guid, autoGroup, false, false);

            if (entry != null)
            {
                entry.SetAddress(Path.GetFileName(assetPath).Replace(" ", ""), false);
                entry.labels.Clear(); //清空标签 后续如果需要标签在自动化打包地方添加
                if (lable == "")
                    entry.SetLabel(Path.GetFileName(assetPath).Replace(" ", "").ToLower(), true, true, false);
                else
                    entry.SetLabel(lable, true, true, false);
            }

            return entry;
        }

        public static bool TryGetGroup(AddressableAssetSettings settings, string groupName,
            out AddressableAssetGroup group)
        {
            if (string.IsNullOrWhiteSpace(groupName))
            {
                group = settings.DefaultGroup;
                return true;
            }

            group = settings.groups.Find(g => string.Equals(g.Name, groupName.Trim()));
            return group == null ? false : true;
        }

        private static AddressableAssetGroup CreateAssetGroup<SchemaType>(AddressableAssetSettings settings,
            string groupName)
        {
            return settings.CreateGroup(groupName, false, false, false,
                new List<AddressableAssetGroupSchema> { settings.DefaultGroup.Schemas[0] },
                typeof(SchemaType));
        }
    }
}